package cn.com.nes.site.rocketmq.handler;

import cn.com.nes.site.entity.UserInfo;
import cn.com.nes.site.entity.bo.crm.saleOrder.AgentRetailSaleBO;
import cn.com.nes.site.entity.bo.crm.saleOrder.AgentSaleDetailVO;
import cn.com.nes.site.entity.bo.crm.saleOrder.AgentSaleMasterVO;
import cn.com.nes.site.entity.dto.CreateCrmFlowDataResultDTO;
import cn.com.nes.site.entity.dto.product.GGoodsDTO;
import cn.com.nes.site.entity.em.crm.clue.ClueClaimTypeEnum;
import cn.com.nes.site.entity.em.crm.clue.ClueSourceEnum;
import cn.com.nes.site.entity.em.crm.customer.CustomerLevelEnum;
import cn.com.nes.site.entity.em.crm.customer.CustomerNatureEnum;
import cn.com.nes.site.entity.em.crm.customer.CustomerSaveTypeEnum;
import cn.com.nes.site.entity.em.crm.customer.EnergyTypeEnum;
import cn.com.nes.site.entity.em.crm.opportunity.DeclareCategoryEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityClassificationEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityStageEnum;
import cn.com.nes.site.entity.em.crm.opportunity.OpportunityTypeEnum;
import cn.com.nes.site.entity.em.crm.saleorder.SaleOrderPayModelEnum;
import cn.com.nes.site.entity.em.crm.saleorder.SaleOrderStatusEnum;
import cn.com.nes.site.entity.em.crm.saleorder.SaleOrderTypeEnum;
import cn.com.nes.site.entity.em.project.ProjectRelationDataTypeEnum;
import cn.com.nes.site.modules.opportuntiy.OpportunityBusiness;
import cn.com.nes.site.rocketmq.strategy.MessageHandler;
import cn.com.nes.site.rocketmq.strategy.Topic;
import cn.com.nes.site.service.crm.clue.CrmClueService;
import cn.com.nes.site.service.crm.clue.bo.ClueBO;
import cn.com.nes.site.service.crm.clue.bo.ClueSaveBO;
import cn.com.nes.site.service.crm.customer.CrmCustomerService;
import cn.com.nes.site.service.crm.customer.CustomerHouseService;
import cn.com.nes.site.service.crm.customer.bo.CustomerBO;
import cn.com.nes.site.service.crm.customer.bo.CustomerHouseBO;
import cn.com.nes.site.service.crm.opportunity.bo.OpportunityBO;
import cn.com.nes.site.service.crm.order.SaleOrderInfoService;
import cn.com.nes.site.service.crm.order.bo.SaleDetailBO;
import cn.com.nes.site.service.crm.order.bo.SaleMasterBO;
import cn.com.nes.site.service.crm.order.bo.SaleOrderBO;
import cn.com.nes.site.service.product.GGoodsService;
import cn.com.nes.site.service.system.company.CompanyMerchantService;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.MessageExt;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

/**
 * 销售订单消费者处理类
 * 接收到的数据全部是已经支付的
 * 保存同步来的销售订单数据,同时生成线索、客户、商机这三块的数据
 */
@Topic("mall2agent_order_topic")
@Component
@Slf4j
public class Mall2AgentOrderHandler implements MessageHandler {

    @Resource
    private GGoodsService gGoodsService;

    @Resource
    private CompanyMerchantService companyMerchantService;

    @Resource
    private CrmClueService crmClueService;

    @Resource
    private CrmCustomerService crmCustomerService;

    @Resource
    private CustomerHouseService customerHouseService;

    @Resource
    private OpportunityBusiness opportunityBusiness;

    @Resource
    private SaleOrderInfoService saleOrderInfoService;

    private final ThreadLocal<String> localCompanyId = new ThreadLocal<>();

    private final ThreadLocal<Map<String, GGoodsDTO>> localGoodsMap = new ThreadLocal<>();

    private final ThreadLocal<CreateCrmFlowDataResultDTO> localResult = new ThreadLocal<>();

    private static final int MAX_THREAD_POOL_SIZE = 4; // 最大线程池大小

    @Override
    public void handleMessage(MessageExt message) {
        String messageBody = new String(message.getBody());
        log.info("处理 mall2agent_order_topic 消息:{}", messageBody);
        try {
            // 转换消息内容
            ObjectMapper objectMapper = new ObjectMapper();
            // 创建销售流程数据
            createCrmFlowData(objectMapper.readValue(messageBody, AgentRetailSaleBO.class));
        } catch (Exception e) {
            log.error("处理消息-同步销售订单数据异常,异常原因:{}", e.getMessage());
            log.error("exceptionStackTrace:", e);
        } finally {
            // 清空ThreadLocal数据
            localGoodsMap.remove();
            localResult.remove();
        }
    }

    // 多线程处理 - 根据不同的店铺创建销售数据
    private void createCrmFlowData(AgentRetailSaleBO agentRetailSaleBO) throws Exception {
        // 取出销售主单
        List<AgentSaleMasterVO> saleMasterList = agentRetailSaleBO.getSaleMasters();
        // 创建线程池
        ExecutorService executorService = Executors.newFixedThreadPool(Math.min(saleMasterList.size(), MAX_THREAD_POOL_SIZE));
        // 创建计数器
        CountDownLatch countDownLatch = new CountDownLatch(saleMasterList.size());
        // 记录失败数量 - 使用 AtomicInteger 确保线程安全的计数
        AtomicInteger faultCount = new AtomicInteger(0);
        // 保存数据
        try {
            // 启动线程池
            for (AgentSaleMasterVO saleMasterVO : saleMasterList) {
                executorService.submit(() -> {
                    try {
                        // 根据店铺id获取对应公司id
                        localCompanyId.set(companyMerchantService.queryCompanyIdByMerId(saleMasterVO.getMerId()));
                        // 保存线索数据
                        localResult.set(new CreateCrmFlowDataResultDTO(crmClueService.saveClue(buildClueBO(agentRetailSaleBO))));
                        queryGoodsInfo(saleMasterVO);
                        // 创建客户数据
                        localResult.get().setCustomer(crmCustomerService.onlySaveCustomer(buildCustomerBO(agentRetailSaleBO)));
                        // 创建房屋数据
                        localResult.get().setCustomerHouse(customerHouseService.queryOrSaveCustomerHouse(buildCustomerHouseBO(agentRetailSaleBO)));
                        // 创建商机数据
                        localResult.get().setOpportunity(opportunityBusiness.save(buildOpportunityBO(agentRetailSaleBO, saleMasterVO)));
                        // 创建销售订单数据
                        saleOrderInfoService.saleOrderSave(buildSaleOrderBO(agentRetailSaleBO, saleMasterVO));
                    } catch (Exception e) {
                        faultCount.incrementAndGet();
                        log.error("同步商城数据失败,订单id:{},店铺id:{}", saleMasterVO.getOrderNo(), saleMasterVO.getMerId());
                        log.error("失败原因:", e);
                        // 中断线程
                        Thread.currentThread().interrupt();
                    } finally {
                        countDownLatch.countDown();
                    }
                });
            }
            // 等待任务执行完成
            countDownLatch.await();
            log.info("商城订单数据同步完成,共有{}个店铺的数据,失败{}条", saleMasterList.size(), faultCount.get());
        } catch (Exception e) {
            log.error("同步商城数据失败,失败原因:" + e);
        } finally {
            executorService.shutdown();
        }
    }

    // 查询产品信息
    private void queryGoodsInfo(AgentSaleMasterVO saleMasterVO) throws Exception {
        // 准备一个map保存产品的信息
        Map<String, GGoodsDTO> map = new HashMap<>();
        // 匹配热链云的产品
        for (AgentSaleDetailVO agentSaleDetailVO : saleMasterVO.getChildList()) {
            GGoodsDTO goodsDetail = gGoodsService.getGoodsDetailByBarCode(localCompanyId.get(), agentSaleDetailVO.getEquipmentId());
            if (ObjectUtil.isNull(goodsDetail)) {
                continue;
            }
            map.put(agentSaleDetailVO.getEquipmentId(), goodsDetail);
        }
        log.info("根据商城订单匹配热链云产品:{}", map.values());
        localGoodsMap.set(map);
    }

    // 构建 线索bo
    private ClueBO buildClueBO(AgentRetailSaleBO agentRetailSaleBO) {
        ClueBO clueBO = ClueBO.builder().build();
        ClueSaveBO clueSaveBO = new ClueSaveBO();
        clueSaveBO.setClaimType(ClueClaimTypeEnum.NOT_CLAIM);
        clueSaveBO.setCustomerNature(CustomerNatureEnum._personal);
        clueSaveBO.setClueSource(ClueSourceEnum.XINCUN_MALL.getClueSourceCode());
        clueSaveBO.setClueName(agentRetailSaleBO.getCustomerName() + "-商城线索");
        clueSaveBO.setClueContact(agentRetailSaleBO.getCustomerName());
        clueSaveBO.setCluePhone(agentRetailSaleBO.getPhone());
        clueSaveBO.setClueMemo("商城推送订单信息自动生成线索");
        clueSaveBO.setAreaCode(agentRetailSaleBO.getAreaCode());
        clueSaveBO.setClueAddress(agentRetailSaleBO.getAddress());
        clueSaveBO.setLongitude(ObjectUtil.isNull(agentRetailSaleBO.getLongitude()) ? null : agentRetailSaleBO.getLongitude().doubleValue());
        clueSaveBO.setLatitude(ObjectUtil.isNull(agentRetailSaleBO.getLatitude()) ? null : agentRetailSaleBO.getLatitude().doubleValue());
        clueSaveBO.setPersonPost(StrUtil.EMPTY); // 商城拿不到客户的职务
        clueSaveBO.setJsonData(StrUtil.EMPTY_JSON);

        clueBO.setAddClue(true);
        clueBO.setClueSaveBO(clueSaveBO);
        UserInfo userInfo = new UserInfo();
        userInfo.setCompanyName(StrUtil.EMPTY);
        clueBO.setUserInfo(userInfo);
        clueBO.setOperateUserCompanyId(localCompanyId.get());
        clueBO.setOperateUserName("默认管理员");
        log.info("构造线索BO:{}", clueBO);
        return clueBO;
    }

    // 构建 客户bo
    private CustomerBO buildCustomerBO(AgentRetailSaleBO agentRetailSaleBO) {
        CustomerBO customerBO = new CustomerBO();
        customerBO.setOperateUserCompanyId(localCompanyId.get());
        customerBO.setMerCustomerId(agentRetailSaleBO.getUserId());
        customerBO.setSaveSource(agentRetailSaleBO.getSaveSoure());
        customerBO.setCustomerName(agentRetailSaleBO.getCustomerName());
        customerBO.setContact(agentRetailSaleBO.getCustomerName());
        customerBO.setPhone(agentRetailSaleBO.getPhone());
        customerBO.setCustomerNature(CustomerNatureEnum._personal);
        customerBO.setBusinessType(null); // 默认为null
        customerBO.setXzqhdm(agentRetailSaleBO.getAreaCode());
        customerBO.setAddress(agentRetailSaleBO.getAddress());
        customerBO.setLongitude(agentRetailSaleBO.getLongitude());
        customerBO.setLatitude(agentRetailSaleBO.getLatitude());
        customerBO.setMemo("商城推送订单信息自动生成客户");
        customerBO.setSaveType(CustomerSaveTypeEnum._my);
        customerBO.setEnergyType(EnergyTypeEnum.getEnum(getEnergyTypeCodeList().get(0)));
        customerBO.setCustomerLevel(CustomerLevelEnum._level_5);
        customerBO.setClueId(localResult.get().getClue().getUuid());
        customerBO.setCustomerSource(localResult.get().getClue().getClueSource());
        customerBO.setIdCardNumber(agentRetailSaleBO.getIdCardNumber());
        customerBO.setHouseNumber(agentRetailSaleBO.getHouseNumber());

        log.info("构造客户BO:{}", customerBO);
        return customerBO;
    }

    // 构建 客户房屋bo
    private CustomerHouseBO buildCustomerHouseBO(AgentRetailSaleBO agentRetailSaleBO) {
        CustomerHouseBO customerHouseBO = new CustomerHouseBO();
        customerHouseBO.setCompanyId(localCompanyId.get());
        customerHouseBO.setOperateUserCompanyId(localCompanyId.get());
        customerHouseBO.setCustomerUuid(localResult.get().getCustomer().getUuid());
        customerHouseBO.setAreaCode(StrUtil.isBlank(agentRetailSaleBO.getAreaCode()) ? StrUtil.EMPTY : agentRetailSaleBO.getAreaCode());
        customerHouseBO.setLongitude(agentRetailSaleBO.getLongitude());
        customerHouseBO.setLatitude(agentRetailSaleBO.getLatitude());
        customerHouseBO.setAddress(agentRetailSaleBO.getAddress());
        customerHouseBO.setHouseNumber(agentRetailSaleBO.getHouseNumber());
        customerHouseBO.setOperateUserId((long)131); // 默认admin的id

        log.info("构造房屋BO:{}", customerHouseBO);
        return customerHouseBO;
    }

    // 构建 商机bo
    private OpportunityBO buildOpportunityBO(AgentRetailSaleBO agentRetailSaleBO, AgentSaleMasterVO saleMasterVO) {
        OpportunityBO opportunityBO = new OpportunityBO();
        opportunityBO.setSaveSource(agentRetailSaleBO.getSaveSoure());
        opportunityBO.setOpportunityName(agentRetailSaleBO.getCustomerName() + " - 零售销售");
        opportunityBO.setAreaCode(agentRetailSaleBO.getAreaCode());
        opportunityBO.setProjectAddress(agentRetailSaleBO.getAddress());
        opportunityBO.setMobilizationTime(agentRetailSaleBO.getPayTime());
        opportunityBO.setOrderGoodsTime(agentRetailSaleBO.getPayTime());
        opportunityBO.setEquiNumber(saleMasterVO.getChildList().stream().mapToInt(AgentSaleDetailVO::getCount).sum());
        opportunityBO.setOpportunityMoney(saleMasterVO.getTotalPrice());
        opportunityBO.setEstimatedClosingDate(agentRetailSaleBO.getPayTime());
        opportunityBO.setCgfPhone(agentRetailSaleBO.getPhone());
        opportunityBO.setLongitude(agentRetailSaleBO.getLongitude());
        opportunityBO.setLatitude(agentRetailSaleBO.getLatitude());
        opportunityBO.setPersonInCharge(agentRetailSaleBO.getCustomerName());
        opportunityBO.setPersonInChargePhone(agentRetailSaleBO.getPhone());
        opportunityBO.setCustomerUuid(localResult.get().getCustomer().getUuid());
        opportunityBO.setClueId(localResult.get().getClue().getUuid());
        opportunityBO.setOperateUserCompanyId(localCompanyId.get());
        // ----------下面是默认值----------
        opportunityBO.setMemo("同步商城订单数据自动生成商机");
        opportunityBO.setEnergyType(EnergyTypeEnum.getEnum(getEnergyTypeCodeList().get(0)));
        opportunityBO.setAddOpportunity(Boolean.TRUE);
        opportunityBO.setProjectRelationDataTypeEnum(ProjectRelationDataTypeEnum.SYSTEM_GENERATED);
        opportunityBO.setOpportunityStage(OpportunityStageEnum._transaction);
        opportunityBO.setOpportunityType(OpportunityTypeEnum._purchase);
        opportunityBO.setOpportunityClassification(OpportunityClassificationEnum.RETAIL);
        opportunityBO.setOpportunityStage(OpportunityStageEnum._transaction);
        opportunityBO.setOpportunityType(OpportunityTypeEnum._purchase);
        opportunityBO.setCategoryOfDeclaration(DeclareCategoryEnum.NEW);
        opportunityBO.setOperateUserId((long)131);
        opportunityBO.setOperateUserName(StrUtil.EMPTY);
        UserInfo userInfo = new UserInfo();
        userInfo.setCompanyName(StrUtil.EMPTY);
        opportunityBO.setUserInfo(userInfo);

        log.info("构造商机BO:{}", opportunityBO);
        return opportunityBO;
    }

    // 构建 销售订单bo
    private SaleOrderBO buildSaleOrderBO(AgentRetailSaleBO agentRetailSaleBO, AgentSaleMasterVO saleMasterVO) {
        SaleOrderBO saleOrderBO = new SaleOrderBO();
        // 设置属性值
        BeanUtils.copyProperties(agentRetailSaleBO, saleOrderBO);
        saleOrderBO.setMallOrderId(saleMasterVO.getOrderNo());
        saleOrderBO.setCompanyId(localCompanyId.get());
        saleOrderBO.setCustomerUuid(localResult.get().getCustomer().getUuid());
        saleOrderBO.setOpportunityUuid(localResult.get().getOpportunity().getUuid());
        saleOrderBO.setAddOrder(Boolean.TRUE);
        saleOrderBO.setSaleOrderName(agentRetailSaleBO.getCustomerName() + " - 零售订单");
        saleOrderBO.setInstallAddress(agentRetailSaleBO.getAddress());
        saleOrderBO.setRealTradingTime(agentRetailSaleBO.getPayTime());
        saleOrderBO.setPayModel(SaleOrderPayModelEnum.PAIED_AFTER_INSTALL);
        saleOrderBO.setSaleOrderStatus(SaleOrderStatusEnum.PAID_SUCCESS);
        saleOrderBO.setOrderType(SaleOrderTypeEnum.PERSONAL);
        saleOrderBO.setCommit(Boolean.TRUE);
        saleOrderBO.setStatus(SaleOrderStatusEnum.PAID_SUCCESS);
        saleOrderBO.setDiscount(100);
        saleOrderBO.setDataSource("商城同步订单");
        saleOrderBO.setHouseId(String.valueOf(localResult.get().getCustomerHouse().getId()));
        // 准备公共容器
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<SaleDetailBO> saleDetailBOList = new ArrayList<>();
        // 从goodsMap取出对应的设备信息,再组装具体参数
        for (AgentSaleDetailVO agentSaleDetailVO : saleMasterVO.getChildList()) {
            // 取出对应产品信息
            GGoodsDTO gGoodsDTO = localGoodsMap.get().get(agentSaleDetailVO.getEquipmentId());
            if (ObjectUtil.isNull(gGoodsDTO)) {
                continue;
            }
            // 构造新的SaleDetailBO
            SaleDetailBO saleDetailBO = new SaleDetailBO();
            BeanUtils.copyProperties(saleOrderBO, saleDetailBO);
            saleDetailBO.setBrandId(String.valueOf(gGoodsDTO.getBrandId()));
            saleDetailBO.setEquipmentId(gGoodsDTO.getSblx());
            saleDetailBO.setEquipmentName(gGoodsDTO.getGoodsName());
            saleDetailBO.setGuidePrice(agentSaleDetailVO.getGuidePrice());
            saleDetailBO.setPrice(agentSaleDetailVO.getGuidePrice());
            saleDetailBO.setCount(agentSaleDetailVO.getCount());
            saleDetailBO.setDiscount(100);
            saleDetailBO.setUnit(Integer.valueOf(gGoodsDTO.getUnit()));
            saleDetailBO.setCompanyId(saleOrderBO.getCompanyId());
            saleDetailBO.setTotalPrice(agentSaleDetailVO.getTotalPrice());
            saleDetailBO.setEquipmentModel(agentSaleDetailVO.getEquipmentId());
            saleDetailBOList.add(saleDetailBO);
            totalAmount = totalAmount.add(agentSaleDetailVO.getTotalPrice());
        }
        SaleMasterBO saleMasterBO = new SaleMasterBO();
        saleMasterBO.setDiscount(100);
        saleMasterBO.setTotalPrice(totalAmount);
        saleMasterBO.setTotalOffer(totalAmount);
        saleMasterBO.setSaleDetails(saleDetailBOList);
        saleMasterBO.setBuildId(String.valueOf(localResult.get().getCustomerHouse().getId()));
        saleMasterBO.setOperateUserId((long)131);
        saleMasterBO.setSaleMasterName(saleMasterVO.getName());

        // 设置属性值
        saleOrderBO.setSaleMasters(Collections.singletonList(saleMasterBO));
        saleOrderBO.setTotalOffer(saleMasterBO.getTotalOffer());
        saleOrderBO.setTotalPrice(saleMasterBO.getTotalPrice());
        log.info("构造销售订单BO:{}", saleOrderBO);
        return saleOrderBO;
    }

    // 获取能源类型编码列表
    private List<String> getEnergyTypeCodeList() {
        List<String> energyTypeCodeList = localGoodsMap.get()
                .values()
                .stream()
                .flatMap(value -> value.getEnergyTypeCodeSet().stream())
                .filter(Objects::nonNull)
                .collect(Collectors.toList());

        energyTypeCodeList = energyTypeCodeList.isEmpty() ? Collections.singletonList(EnergyTypeEnum._0.getKey()) : energyTypeCodeList;
        return energyTypeCodeList.stream().distinct().collect(Collectors.toList());
    }

}
